package com.person.jiaiplan.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Console;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.person.jiaiplan.mapper.ExpensesCountLogsMapper;
import com.person.jiaiplan.pojo.dto.expenses.ExpensesCountListResDTO;
import com.person.jiaiplan.pojo.dto.expenses.ExpensesCountReqDTO;
import com.person.jiaiplan.pojo.dto.expenses.ExpensesCountResDTO;
import com.person.jiaiplan.pojo.dto.expenses.NoPlanExpensesReqDTO;
import com.person.jiaiplan.pojo.entity.ExpensesCountLogs;
import com.person.jiaiplan.pojo.signle.SignleSnowFlake;
import com.person.jiaiplan.service.ExpensesCountLogsService;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.LinkedList;
import java.util.List;

@Service
public class ExpensesCountLogsServiceImpl extends ServiceImpl<ExpensesCountLogsMapper, ExpensesCountLogs> implements ExpensesCountLogsService {

    @Override
    public ExpensesCountResDTO queryCount(ExpensesCountReqDTO reqDTO) {
        ExpensesCountResDTO expensesCountResDTO = new ExpensesCountResDTO();
        // 默认查询本月的数据
        if (StrUtil.isBlank(reqDTO.getStartTime()) || StrUtil.isBlank(reqDTO.getEndTime())) {
            reqDTO.setStartTime(DateUtil.format(DateUtil.beginOfMonth(DateUtil.date()), "yyyy-MM-dd"));
            reqDTO.setEndTime(DateUtil.format(DateUtil.endOfMonth(DateUtil.date()), "yyyy-MM-dd"));
        }
        LambdaQueryWrapper<ExpensesCountLogs> queryWrapper = Wrappers.<ExpensesCountLogs>lambdaQuery();
        List<ExpensesCountLogs> expensesCountLogs = new LinkedList<>();
        if (reqDTO.getExpensesType() != null) {
            queryWrapper.eq(ExpensesCountLogs::getExpensesType, reqDTO.getExpensesType());
            queryWrapper.between(ExpensesCountLogs::getCreateTime, DateUtil.beginOfDay(DateUtil.parseDate(reqDTO.getStartTime())), DateUtil.endOfDay(DateUtil.parseDate(reqDTO.getEndTime())))
                    .orderByAsc(ExpensesCountLogs::getCreateTime);
            expensesCountLogs = this.list(queryWrapper);
        } else {
            queryWrapper.between(ExpensesCountLogs::getCreateTime, DateUtil.beginOfDay(DateUtil.parseDate(reqDTO.getStartTime())), DateUtil.endOfDay(DateUtil.parseDate(reqDTO.getEndTime())))
                    .ne(ExpensesCountLogs::getExpensesType, 1)
                    .ne(ExpensesCountLogs::getExpensesType, 2)
                    .orderByAsc(ExpensesCountLogs::getCreateTime);
            expensesCountLogs = this.list(queryWrapper);
            // 展示中加入每日类型的花销，不按照时间
            queryWrapper = Wrappers.<ExpensesCountLogs>lambdaQuery();
            queryWrapper.eq(ExpensesCountLogs::getExpensesType, 1);
            expensesCountLogs.addAll(this.list(queryWrapper));
            // 展示中加入在计划还款时间内的分期计划
            queryWrapper = Wrappers.<ExpensesCountLogs>lambdaQuery();
            queryWrapper.eq(ExpensesCountLogs::getExpensesType, 2);
            // 计划开始时间 <= 查询结束时间 && 计划结束时间 >= 查询开始时间
            queryWrapper.le(ExpensesCountLogs::getPlanStartTime, DateUtil.beginOfDay(DateUtil.parseDate(reqDTO.getEndTime())));
            queryWrapper.ge(ExpensesCountLogs::getPlanEndTime, DateUtil.endOfDay(DateUtil.parseDate(reqDTO.getStartTime())));
            expensesCountLogs.addAll(this.list(queryWrapper));
        }

        expensesCountResDTO.setLists(createExpensesCountListResDTO(expensesCountLogs, reqDTO));
        // 创建统计数据
        expensesCountResDTO = createExpensesCountTotal(expensesCountResDTO, expensesCountLogs, reqDTO);


        return expensesCountResDTO;
    }

    @Override
    public Boolean noPlanExpenses(NoPlanExpensesReqDTO reqDTO) {
        ExpensesCountLogs expensesCountLogs = new ExpensesCountLogs();
        expensesCountLogs.setId(SignleSnowFlake.getSnowflakeId());
        expensesCountLogs.setExpensesType(reqDTO.getExpensesType());
        expensesCountLogs.setContent(reqDTO.getContent());
        expensesCountLogs.setRemark(reqDTO.getRemark());
        expensesCountLogs.setFinishTime(DateUtil.parseDate(reqDTO.getRealTime()));
        expensesCountLogs.setRealAmount(new BigDecimal(reqDTO.getRealAmount()));
        expensesCountLogs.setCreateTime(DateUtil.date());
        return this.save(expensesCountLogs);
    }

    private ExpensesCountResDTO createExpensesCountTotal(ExpensesCountResDTO expensesCountResDTO, List<ExpensesCountLogs> expensesCountLogs, ExpensesCountReqDTO reqDTO) {
        // 总花销
        BigDecimal totalAmount = new BigDecimal(0);
        // 计划花销
        BigDecimal totalPlanAmount = new BigDecimal(0);
        // 非计划花销
        BigDecimal totalNoPlanAmount = new BigDecimal(0);
        // 每日实际花销
        BigDecimal totalAmountByDay = new BigDecimal(0);

        int noPlanCounts = 0;
        long days = DateUtil.betweenDay(DateUtil.parseDate(reqDTO.getStartTime()), DateUtil.parseDate(reqDTO.getEndTime()), true) + 1;
        long months = DateUtil.betweenMonth(DateUtil.parseDate(reqDTO.getStartTime()), DateUtil.parseDate(reqDTO.getEndTime()), true) + 1;
        long nowDays = DateUtil.betweenDay(DateUtil.parseDate(reqDTO.getStartTime()), DateUtil.parseDate(DateUtil.now()), true) + 1;
        if (nowDays > days) {
            nowDays = days;
        }
        Console.log("days:{}", days);
        Console.log("nowDays:{}", nowDays);

        for (ExpensesCountLogs vo : expensesCountLogs) {
            // 每日花销
            if (vo.getExpensesType() == 1) {
                totalAmountByDay = totalAmountByDay.add(vo.getRealAmount());
            }
            // 处理分期付款逻辑
            else if (vo.getExpensesType() == 2) {
                totalAmount = vo.getRealAmount().multiply(new BigDecimal(months)).add(totalAmount);
                totalPlanAmount = vo.getEstimatedAmount().multiply(new BigDecimal(months)).add(totalPlanAmount);
            } else {
                // 实际花销
                totalAmount = totalAmount.add(vo.getRealAmount());
                // 非计划花销
                if (vo.getExpensesType() > 5) {
                    totalNoPlanAmount = totalNoPlanAmount.add(vo.getRealAmount());
                    noPlanCounts++;
                } else {
                    // 计划花销
                    totalPlanAmount = totalPlanAmount.add(vo.getEstimatedAmount());
                }
            }
        }
        // 计划花销和实际花销要加上 每日花销乘以天数
        totalAmount = totalAmountByDay.multiply(new BigDecimal(nowDays)).add(totalAmount);
        totalPlanAmount = totalAmountByDay.multiply(new BigDecimal(days)).add(totalPlanAmount);

        expensesCountResDTO.setPlanAmountTotal(totalPlanAmount.toString() + " ￥");
        expensesCountResDTO.setRealAmountTotal(totalAmount.toString() + " ￥");
        expensesCountResDTO.setNoPlanAmountTotal(totalNoPlanAmount.toString() + " ￥");
        expensesCountResDTO.setNoPlanCounts(String.valueOf(noPlanCounts));
        return expensesCountResDTO;
    }

    /**
     * 创建花销返回list对象
     *
     * @param expensesCountLogs
     * @return
     */
    private List<ExpensesCountListResDTO> createExpensesCountListResDTO(List<ExpensesCountLogs> expensesCountLogs, ExpensesCountReqDTO reqDTO) {
        List<ExpensesCountListResDTO> list = new LinkedList<>();

        expensesCountLogs.stream().forEach(vo -> {
            ExpensesCountListResDTO expensesCountResDTO = new ExpensesCountListResDTO();
            expensesCountResDTO.setId(String.valueOf(vo.getId()));
            expensesCountResDTO.setPlanId(String.valueOf(vo.getPlanId()));
            expensesCountResDTO.setExpensesType(vo.getExpensesType());
            expensesCountResDTO.setContent(vo.getContent());
            expensesCountResDTO.setRemark(vo.getRemark());
            expensesCountResDTO.setPlanStartTime(DateUtil.formatDate(vo.getPlanStartTime()));
            expensesCountResDTO.setPlanFinishTime(DateUtil.formatDate(vo.getPlanEndTime()));
            if (vo.getEstimatedAmount() == null) {
                expensesCountResDTO.setEstimatedAmountStr(" - ");
            } else {
                expensesCountResDTO.setEstimatedAmountStr(vo.getEstimatedAmount() + " ￥");
                if (vo.getExpensesType() == 2) {
                    expensesCountResDTO.setEstimatedAmountStr("每期 " + vo.getEstimatedAmount() + " ￥ ");
                }

            }
            if (vo.getRealAmount() == null) {
                expensesCountResDTO.setRealAmountStr(" - ");
            } else {
                expensesCountResDTO.setRealAmountStr(vo.getRealAmount() + " ￥");
                expensesCountResDTO.setRealAmount(String.valueOf(vo.getRealAmount()));
                // 对于分期的花销，需要按时间计算实际金额
                if (vo.getExpensesType() == 2) {
                    expensesCountResDTO.setRealAmountStr("每期 " + vo.getRealAmount() + " ￥");
                }
            }

            if (vo.getFinishTime() == null) {
                expensesCountResDTO.setRealTime("-");
            } else {
                expensesCountResDTO.setRealTime(DateUtil.format(vo.getFinishTime(), "yyyy-MM-dd"));
            }

            if (vo.getPlanStartTime() == null) {
                expensesCountResDTO.setPlanTime("-");
            } else if (vo.getPlanStartTime() != null) {
                String planTime = DateUtil.format(vo.getPlanStartTime(), "yyyy-MM-dd");
                if (vo.getPlanEndTime() != null) {
                    planTime = planTime + " - " + DateUtil.format(vo.getPlanEndTime(), "yyyy-MM-dd");
                }
                expensesCountResDTO.setPlanTime(planTime);
            }

            list.add(expensesCountResDTO);
        });
        // 根据类型和 状态排序
        list.sort((o1, o2) -> o1.getExpensesType().compareTo(o2.getExpensesType()));
        return list;
    }
}
